import os
import re
from pathlib import Path
from datetime import datetime, timedelta

# ==================== 配置选项 ====================
# 在这里修改配置，无需修改代码其他部分

# 日志文件目录
LOG_DIR = r"C:\Users\Administrator\Desktop\1"

# 输出目录
OUTPUT_DIR = r"C:\Users\Administrator\Desktop\1\extracted_messages"

# 时间范围过滤（设置为None表示不过滤）
START_TIME = None  # 格式: datetime(2025, 8, 4, 11, 26, 00)
END_TIME = None    # 格式: datetime(2025, 8, 4, 12, 29, 00)

# 目标traceid过滤（设置为None表示不过滤）
TARGET_TRACEID = "d859139f-453e-44bb-96c4-c3098a153ba6"

# 是否自动删除反斜杠
AUTO_REMOVE_BACKSLASH = True

# 是否显示详细进度
SHOW_DETAILED_PROGRESS = True

# 进度显示间隔（行数）
PROGRESS_INTERVAL = 10000

# 是否跳过没有数据的文件（不生成空文档）
SKIP_EMPTY_FILES = True

# 是否将所有结果合并到一个文件
MERGE_ALL_TO_ONE_FILE = True

# 合并文件的名称
MERGED_FILE_NAME = "merged_extracted_messages.txt"

# ==================== 脚本代码 ====================

def parse_timestamp(timestamp_str):
    """
    解析日志中的时间戳
    格式: 2025-08-04 09:51:57.099
    """
    try:
        # 解析时间戳，支持毫秒精度
        return datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
    except ValueError:
        try:
            # 如果没有毫秒，尝试不带毫秒的格式
            return datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S')
        except ValueError:
            return None

def extract_timestamp_from_line(line):
    """
    从日志行中提取时间戳
    """
    # 匹配时间戳格式: YYYY-MM-DD HH:MM:SS.ms
    timestamp_pattern = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d{3})?)'
    match = re.search(timestamp_pattern, line)
    if match:
        return parse_timestamp(match.group(1))
    return None

def extract_traceid_from_line(line):
    """
    从日志行中提取traceid
    格式: traceid:5a83379e-abf0-4965-b8de-79d44e2de5af@STANDARD
    只提取@前面的部分
    """
    # 匹配traceid格式，只提取@前面的部分
    traceid_pattern = r'traceid:([a-f0-9\-]+)@'
    match = re.search(traceid_pattern, line)
    if match:
        return match.group(1)  # 只返回@前面的traceid部分
    return None

def is_line_in_time_range(line, start_time=None, end_time=None):
    """
    检查日志行是否在指定的时间范围内
    """
    if start_time is None and end_time is None:
        return True  # 如果没有指定时间范围，返回所有行
    
    timestamp = extract_timestamp_from_line(line)
    if timestamp is None:
        return False  # 如果无法解析时间戳，跳过该行
    
    if start_time and timestamp < start_time:
        return False
    
    if end_time and timestamp > end_time:
        return False
    
    return True

def is_line_contains_traceid(line, target_traceid=None):
    """
    检查日志行是否包含指定的traceid
    """
    if target_traceid is None:
        return True  # 如果没有指定traceid，返回所有行
    
    line_traceid = extract_traceid_from_line(line)
    if line_traceid is None:
        return False  # 如果无法解析traceid，跳过该行
    
    return line_traceid == target_traceid

def extract_messages_from_log(log_file_path, output_file_path, start_time=None, end_time=None, target_traceid=None):
    """
    从日志文件中提取包含 '|desc: message:' 的行，支持时间过滤和traceid过滤
    """
    extracted_messages = []
    line_count = 0
    filtered_count = 0
    
    print(f"开始处理文件: {log_file_path}")
    
    # 获取文件大小
    try:
        file_size = os.path.getsize(log_file_path)
        print(f"文件大小: {file_size / (1024*1024):.2f} MB")
    except OSError as e:
        print(f"警告: 无法获取文件大小: {e}")
    
    if start_time:
        print(f"开始时间: {start_time}")
    if end_time:
        print(f"结束时间: {end_time}")
    if target_traceid:
        print(f"目标traceid: {target_traceid}")
    
    try:
        with open(log_file_path, 'r', encoding='utf-8', errors='ignore') as file:
            for line_num, line in enumerate(file, 1):
                line_count += 1
                
                # 显示进度
                if SHOW_DETAILED_PROGRESS and line_count % PROGRESS_INTERVAL == 0:
                    print(f"已处理 {line_count:,} 行，过滤后 {filtered_count:,} 行...")
                
                # 首先检查时间范围
                if not is_line_in_time_range(line, start_time, end_time):
                    continue
                
                # 然后检查traceid
                if not is_line_contains_traceid(line, target_traceid):
                    continue
                
                filtered_count += 1
                
                # 查找包含 '|desc: message:' 的行
                if '|desc: message:' in line:
                    # 提取消息部分
                    message_start = line.find('|desc: message:')
                    if message_start != -1:
                        message_content = line[message_start + len('|desc: message:'):].strip()
                        
                        # 自动删除所有反斜杠
                        if AUTO_REMOVE_BACKSLASH:
                            message_content = message_content.replace('\\', '')
                        
                        # 提取时间戳用于显示
                        timestamp = extract_timestamp_from_line(line)
                        timestamp_str = timestamp.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3] if timestamp else "未知时间"
                        
                        # 提取traceid用于显示
                        traceid = extract_traceid_from_line(line)
                        traceid_str = traceid if traceid else "未知traceid"
                        
                        extracted_messages.append(f"时间: {timestamp_str}\nTraceID: {traceid_str}\n行号: {line_num}\n消息: {message_content}\n{'='*50}\n")
                        print(f"找到第 {len(extracted_messages)} 条消息 (行号: {line_num}, 时间: {timestamp_str}, TraceID: {traceid_str})")
        
        print(f"文件处理完成，总共处理了 {line_count:,} 行，过滤后 {filtered_count:,} 行")
        
        # 将提取的消息写入输出文件
        with open(output_file_path, 'w', encoding='utf-8') as output_file:
            output_file.write(f"从文件 {log_file_path} 提取的消息:\n")
            if start_time:
                output_file.write(f"开始时间: {start_time}\n")
            if end_time:
                output_file.write(f"结束时间: {end_time}\n")
            if target_traceid:
                output_file.write(f"目标TraceID: {target_traceid}\n")
            output_file.write(f"总共提取到 {len(extracted_messages)} 条消息\n")
            if AUTO_REMOVE_BACKSLASH:
                output_file.write("注意: 已自动删除所有反斜杠\n")
            output_file.write("="*50 + "\n\n")
            
            for message in extracted_messages:
                output_file.write(message)
        
        print(f"成功从 {log_file_path} 提取了 {len(extracted_messages)} 条消息")
        if AUTO_REMOVE_BACKSLASH:
            print("已自动删除所有反斜杠")
        print(f"结果已保存到: {output_file_path}")
        
        return len(extracted_messages)
        
    except FileNotFoundError:
        print(f"错误: 文件 {log_file_path} 不存在")
        return 0
    except PermissionError:
        print(f"错误: 没有权限访问文件 {log_file_path}")
        return 0
    except UnicodeDecodeError as e:
        print(f"错误: 文件编码问题 {log_file_path}: {e}")
        return 0
    except Exception as e:
        print(f"处理文件 {log_file_path} 时出错: {str(e)}")
        import traceback
        traceback.print_exc()
        return 0

def main():
    # 显示当前配置
    print("当前配置:")
    print(f"  日志文件目录: {LOG_DIR}")
    print(f"  输出目录: {OUTPUT_DIR}")
    print(f"  开始时间: {START_TIME}")
    print(f"  结束时间: {END_TIME}")
    print(f"  目标TraceID: {TARGET_TRACEID}")
    print(f"  自动删除反斜杠: {AUTO_REMOVE_BACKSLASH}")
    print(f"  显示详细进度: {SHOW_DETAILED_PROGRESS}")
    print(f"  进度显示间隔: {PROGRESS_INTERVAL:,} 行")
    print(f"  跳过空文件: {SKIP_EMPTY_FILES}")
    print(f"  合并到单个文件: {MERGE_ALL_TO_ONE_FILE}")
    if MERGE_ALL_TO_ONE_FILE:
        print(f"  合并文件名: {MERGED_FILE_NAME}")
    print()
    
    # 检查目录是否存在
    if not os.path.exists(LOG_DIR):
        print(f"错误: 目录 {LOG_DIR} 不存在")
        return
    
    # 创建输出目录
    os.makedirs(OUTPUT_DIR, exist_ok=True)
    print(f"输出目录已创建: {OUTPUT_DIR}")
    
    # 获取所有log文件
    log_files = [f for f in os.listdir(LOG_DIR) if f.endswith('.log')]
    
    print(f"\n找到 {len(log_files)} 个日志文件:")
    for file in log_files:
        file_path = os.path.join(LOG_DIR, file)
        try:
            file_size = os.path.getsize(file_path) / (1024*1024)
            print(f"  - {file} ({file_size:.2f} MB)")
        except OSError:
            print(f"  - {file} (无法获取大小)")
    
    if not log_files:
        print("没有找到任何.log文件")
        return
    
    # 处理每个日志文件
    total_messages = 0
    successful_files = 0
    all_extracted_messages = []  # 用于合并所有消息
    
    for i, log_file in enumerate(log_files, 1):
        log_file_path = os.path.join(LOG_DIR, log_file)
        
        # 根据是否合并决定输出文件路径
        if MERGE_ALL_TO_ONE_FILE:
            # 合并模式下使用临时文件
            output_file_path = os.path.join(OUTPUT_DIR, f"temp_{log_file}.txt")
        else:
            output_file_path = os.path.join(OUTPUT_DIR, f"extracted_{log_file}.txt")
        
        print(f"\n{'='*60}")
        print(f"正在处理: {log_file} ({i}/{len(log_files)})")
        print(f"{'='*60}")
        
        # 提取消息
        message_count = extract_messages_from_log(log_file_path, output_file_path, START_TIME, END_TIME, TARGET_TRACEID)
        
        # 处理结果
        if message_count > 0:
            total_messages += message_count
            successful_files += 1
            print(f"文件 {log_file} 提取了 {message_count} 条消息")
            
            # 如果合并模式，读取消息内容
            if MERGE_ALL_TO_ONE_FILE:
                try:
                    with open(output_file_path, 'r', encoding='utf-8') as f:
                        content = f.read()
                        # 提取消息部分（跳过文件头信息）
                        messages_start = content.find("="*50)
                        if messages_start != -1:
                            messages_content = content[messages_start + 50:].strip()
                            if messages_content:
                                all_extracted_messages.append(f"\n{'='*60}\n来自文件: {log_file}\n{'='*60}\n{messages_content}")
                except Exception as e:
                    print(f"无法读取文件 {log_file} 的内容: {e}")
        else:
            print(f"文件 {log_file} 没有找到目标TraceID的数据")
            if SKIP_EMPTY_FILES:
                # 删除空文件
                if os.path.exists(output_file_path):
                    try:
                        os.remove(output_file_path)
                        print(f"已删除空文件: {output_file_path}")
                    except Exception as e:
                        print(f"无法删除空文件 {output_file_path}: {e}")
    
    # 如果启用合并模式，创建合并文件
    if MERGE_ALL_TO_ONE_FILE and all_extracted_messages:
        merged_file_path = os.path.join(OUTPUT_DIR, MERGED_FILE_NAME)
        try:
            with open(merged_file_path, 'w', encoding='utf-8') as f:
                f.write(f"合并的提取消息\n")
                f.write(f"总共从 {successful_files} 个文件提取了 {total_messages} 条消息\n")
                if START_TIME:
                    f.write(f"开始时间: {START_TIME}\n")
                if END_TIME:
                    f.write(f"结束时间: {END_TIME}\n")
                if TARGET_TRACEID:
                    f.write(f"目标TraceID: {TARGET_TRACEID}\n")
                if AUTO_REMOVE_BACKSLASH:
                    f.write("注意: 已自动删除所有反斜杠\n")
                f.write("="*50 + "\n")
                
                for messages in all_extracted_messages:
                    f.write(messages)
            
            print(f"\n合并文件已创建: {merged_file_path}")
            
            # 清理临时文件
            for log_file in log_files:
                temp_file = os.path.join(OUTPUT_DIR, f"temp_{log_file}.txt")
                if os.path.exists(temp_file):
                    try:
                        os.remove(temp_file)
                    except Exception as e:
                        print(f"无法删除临时文件 {temp_file}: {e}")
            
        except Exception as e:
            print(f"创建合并文件时出错: {e}")
    
    print(f"\n{'='*60}")
    print("所有文件处理完成！")
    print(f"提取的消息保存在: {OUTPUT_DIR}")
    print(f"成功处理了 {successful_files}/{len(log_files)} 个文件")
    if AUTO_REMOVE_BACKSLASH:
        print("所有反斜杠已自动删除")
    if START_TIME or END_TIME:
        print("已应用时间过滤")
    if TARGET_TRACEID:
        print(f"已应用TraceID过滤: {TARGET_TRACEID}")
    if SKIP_EMPTY_FILES:
        print("已跳过没有数据的文件")
    if MERGE_ALL_TO_ONE_FILE:
        print(f"所有结果已合并到: {MERGED_FILE_NAME}")
    print(f"总共提取了 {total_messages} 条消息")
    print(f"{'='*60}")

if __name__ == "__main__":
    main()